/**
 * Hook麦当劳APP - Attach模式（无需Gadget）
 * 
 * 使用方法：
 * 1. 先在模拟器上启动麦当劳APP
 * 2. frida -U "麦当劳" -l hook_mcd_app_attach.js
 * 3. 调用你的API: Invoke-WebRequest "http://120.27.155.222:9999/api/message/send-test"
 * 4. 观察Frida输出，捕获密钥！
 */

console.log("\n" + "=".repeat(100));
console.log("🍔 麦当劳APP - So库加密参数完整捕获");
console.log("=".repeat(100) + "\n");

// 延迟执行，等待so库加载
setTimeout(function() {
    console.log("🔍 正在搜索so库...\n");
    
    // 查找数美SDK的so库
    var modules = Process.enumerateModules();
    var targetModule = null;
    
    modules.forEach(function(module) {
        var name = module.name.toLowerCase();
        
        // 数美SDK的so库通常包含这些名称
        if (name.indexOf("smsdk") !== -1 || 
            name.indexOf("sm_") !== -1 ||
            name.indexOf("shumei") !== -1 ||
            name.indexOf("antifraud") !== -1) {
            
            console.log("✅ 找到数美SDK so库: " + module.name);
            console.log("   路径: " + module.path);
            console.log("   基址: " + module.base);
            console.log("   大小: " + module.size + " bytes");
            console.log("");
            
            targetModule = module;
        }
    });
    
    if (!targetModule) {
        console.log("⚠️  未找到明显的数美SDK so库，列出所有so库：\n");
        modules.forEach(function(module) {
            if (module.name.indexOf(".so") !== -1) {
                console.log("  - " + module.name);
            }
        });
        console.log("\n💡 如果你知道具体的so库名称，可以手动修改脚本\n");
    }
    
    console.log("\n" + "=".repeat(100));
    console.log("🎯 开始Hook关键函数...");
    console.log("=".repeat(100) + "\n");
    
    // Hook 1: OpenSSL AES加密 - 捕获密钥
    hookAESKey();
    
    // Hook 2: RSA加密 - 捕获ep字段生成
    hookRSAEncrypt();
    
    // Hook 3: Base64编码 - 捕获最终结果
    hookBase64();
    
    // Hook 4: JNI函数 - 捕获返回值
    hookJNIFunctions();
    
    console.log("\n✅ Hook设置完成！");
    console.log("\n" + "=".repeat(100));
    console.log("📱 现在请调用你的API触发麦当劳APP执行：");
    console.log("   Invoke-WebRequest \"http://120.27.155.222:9999/api/message/send-test\"");
    console.log("=".repeat(100) + "\n");
    
}, 2000);

/**
 * Hook AES密钥设置 - 这是最关键的！
 */
function hookAESKey() {
    console.log("📌 [Hook 1/4] AES密钥捕获...");
    
    // 方法1: AES_set_encrypt_key
    try {
        var AES_set_encrypt_key = Module.findExportByName(null, "AES_set_encrypt_key");
        if (AES_set_encrypt_key) {
            console.log("   ✅ Hook AES_set_encrypt_key @ " + AES_set_encrypt_key);
            
            Interceptor.attach(AES_set_encrypt_key, {
                onEnter: function(args) {
                    var keyData = args[0];
                    var keyBits = args[1].toInt32();
                    var keyBytes = keyBits / 8;
                    
                    console.log("\n" + "🔑".repeat(50));
                    console.log("🔑🔑🔑 捕获到AES密钥设置！");
                    console.log("═".repeat(100));
                    
                    if (keyData && keyBytes > 0 && keyBytes <= 32) {
                        try {
                            var keyBuffer = ptr(keyData).readByteArray(keyBytes);
                            var keyArray = new Uint8Array(keyBuffer);
                            
                            // 提取HEX
                            var keyHex = "";
                            for (var i = 0; i < keyArray.length; i++) {
                                keyHex += ("0" + keyArray[i].toString(16)).slice(-2);
                            }
                            
                            console.log("\n  🔐 密钥长度: " + keyBits + " bits (" + keyBytes + " bytes)");
                            console.log("  🔐 密钥 HEX: " + keyHex);
                            console.log("\n  📋 Hexdump:");
                            console.log(hexdump(keyData, { length: keyBytes, header: false, ansi: true }));
                            
                            // 显眼的提示
                            console.log("\n" + "⚠️".repeat(50));
                            console.log("⚠️⚠️⚠️  这就是解密data字段的AES密钥！请复制HEX值！  ⚠️⚠️⚠️");
                            console.log("⚠️".repeat(50));
                            console.log("\n复制这个密钥: " + keyHex);
                            
                            // 记录到全局变量
                            global.capturedAESKey = keyHex;
                            global.capturedAESKeyTime = new Date().toISOString();
                            
                        } catch (e) {
                            console.log("  ❌ 读取密钥失败: " + e);
                        }
                    }
                    
                    console.log("═".repeat(100));
                    console.log("");
                }
            });
        } else {
            console.log("   ⚠️  未找到 AES_set_encrypt_key");
        }
    } catch (e) {
        console.log("   ❌ Hook失败: " + e);
    }
    
    // 方法2: EVP_EncryptInit_ex（OpenSSL高级API）
    try {
        var EVP_EncryptInit_ex = Module.findExportByName(null, "EVP_EncryptInit_ex");
        if (EVP_EncryptInit_ex) {
            console.log("   ✅ Hook EVP_EncryptInit_ex @ " + EVP_EncryptInit_ex);
            
            Interceptor.attach(EVP_EncryptInit_ex, {
                onEnter: function(args) {
                    var key = args[3];
                    var iv = args[4];
                    
                    if (key && !key.isNull()) {
                        console.log("\n🔐 EVP_EncryptInit_ex - 捕获密钥/IV");
                        
                        try {
                            var keyHex = "";
                            var keyBuffer = ptr(key).readByteArray(32);
                            var keyArray = new Uint8Array(keyBuffer);
                            for (var i = 0; i < keyArray.length; i++) {
                                keyHex += ("0" + keyArray[i].toString(16)).slice(-2);
                            }
                            console.log("  密钥 HEX: " + keyHex);
                            
                            global.capturedAESKey = keyHex;
                        } catch (e) {}
                        
                        if (iv && !iv.isNull()) {
                            try {
                                var ivHex = "";
                                var ivBuffer = ptr(iv).readByteArray(16);
                                var ivArray = new Uint8Array(ivBuffer);
                                for (var i = 0; i < ivArray.length; i++) {
                                    ivHex += ("0" + ivArray[i].toString(16)).slice(-2);
                                }
                                console.log("  IV HEX: " + ivHex);
                                global.capturedIV = ivHex;
                            } catch (e) {}
                        }
                        console.log("");
                    }
                }
            });
        } else {
            console.log("   ⚠️  未找到 EVP_EncryptInit_ex");
        }
    } catch (e) {
        console.log("   ❌ Hook失败: " + e);
    }
}

/**
 * Hook RSA加密 - 捕获ep字段生成
 */
function hookRSAEncrypt() {
    console.log("\n📌 [Hook 2/4] RSA加密捕获（ep字段）...");
    
    try {
        var RSA_public_encrypt = Module.findExportByName(null, "RSA_public_encrypt");
        if (RSA_public_encrypt) {
            console.log("   ✅ Hook RSA_public_encrypt @ " + RSA_public_encrypt);
            
            Interceptor.attach(RSA_public_encrypt, {
                onEnter: function(args) {
                    this.flen = args[0].toInt32();
                    this.from = args[1];
                    this.to = args[2];
                    
                    console.log("\n🔐 RSA_public_encrypt 被调用");
                    console.log("  加密数据长度: " + this.flen + " bytes");
                    
                    if (this.from && this.flen > 0 && this.flen <= 256) {
                        try {
                            var buffer = ptr(this.from).readByteArray(this.flen);
                            var array = new Uint8Array(buffer);
                            
                            var dataHex = "";
                            for (var i = 0; i < array.length; i++) {
                                dataHex += ("0" + array[i].toString(16)).slice(-2);
                            }
                            
                            console.log("  原始数据 HEX: " + dataHex);
                            console.log("  原始数据 Hexdump:");
                            console.log(hexdump(this.from, { length: this.flen, header: false }));
                            
                            // 如果长度是32字节，很可能是AES密钥
                            if (this.flen === 32) {
                                console.log("\n  💡 这很可能是AES密钥（32字节）！");
                                console.log("  💡 RSA加密后会变成ep字段");
                            }
                            
                        } catch (e) {}
                    }
                },
                onLeave: function(retval) {
                    var encLen = retval.toInt32();
                    console.log("  RSA加密结果长度: " + encLen + " bytes");
                    
                    if (encLen > 0 && this.to) {
                        try {
                            var buffer = ptr(this.to).readByteArray(encLen);
                            var array = new Uint8Array(buffer);
                            
                            var rsaHex = "";
                            for (var i = 0; i < array.length; i++) {
                                rsaHex += ("0" + array[i].toString(16)).slice(-2);
                            }
                            
                            console.log("  RSA加密结果 HEX: " + rsaHex.substring(0, 100) + "...");
                            console.log("  💡 这个结果会Base64编码后变成ep字段\n");
                            
                            global.capturedRSAResult = rsaHex;
                            
                        } catch (e) {}
                    }
                }
            });
        } else {
            console.log("   ⚠️  未找到 RSA_public_encrypt");
        }
    } catch (e) {
        console.log("   ❌ Hook失败: " + e);
    }
}

/**
 * Hook Base64编码
 */
function hookBase64() {
    console.log("\n📌 [Hook 3/4] Base64编码捕获...");
    
    // Android的Base64
    try {
        Java.perform(function() {
            var Base64 = Java.use("android.util.Base64");
            
            Base64.encodeToString.overload('[B', 'int').implementation = function(input, flags) {
                var result = this.encodeToString(input, flags);
                
                // 只记录长度较长的（可能是加密结果）
                if (result.length > 50) {
                    console.log("\n📊 Base64.encodeToString 被调用");
                    console.log("  输入长度: " + input.length + " bytes");
                    console.log("  输出长度: " + result.length + " chars");
                    console.log("  Base64结果: " + result.substring(0, 100) + (result.length > 100 ? "..." : ""));
                    
                    // 检查是否可能是data或ep字段
                    if (input.length > 100) {
                        console.log("  💡 可能是data字段（加密后的设备信息）");
                    } else if (input.length >= 128 && input.length <= 256) {
                        console.log("  💡 可能是ep字段（RSA加密的AES密钥）");
                    }
                    console.log("");
                }
                
                return result;
            };
            
            console.log("   ✅ Hook android.util.Base64.encodeToString");
        });
    } catch (e) {
        console.log("   ⚠️  Hook Base64失败: " + e);
    }
}

/**
 * Hook JNI函数
 */
function hookJNIFunctions() {
    console.log("\n📌 [Hook 4/4] JNI函数捕获...");
    
    // 等待Java环境初始化
    Java.perform(function() {
        console.log("   ✅ Java环境已就绪");
        
        // 尝试找到数美SDK的类
        try {
            var SmAntiFraud = Java.use("com.ishumei.smantifraud.SmAntiFraud");
            
            // Hook getDeviceId
            if (SmAntiFraud.getDeviceId) {
                SmAntiFraud.getDeviceId.implementation = function() {
                    var result = this.getDeviceId();
                    console.log("\n📞 SmAntiFraud.getDeviceId() 返回: " + result);
                    return result;
                };
                console.log("   ✅ Hook SmAntiFraud.getDeviceId");
            }
            
            // Hook create（通常是初始化）
            if (SmAntiFraud.create) {
                SmAntiFraud.create.overload('android.content.Context', 'java.lang.String').implementation = function(ctx, orgId) {
                    console.log("\n📞 SmAntiFraud.create() 被调用");
                    console.log("  Organization ID: " + orgId);
                    var result = this.create(ctx, orgId);
                    console.log("  返回: " + result);
                    return result;
                };
                console.log("   ✅ Hook SmAntiFraud.create");
            }
            
            // Hook getQueryData（生成加密数据）
            Java.choose("com.ishumei.smantifraud.SmAntiFraud", {
                onMatch: function(instance) {
                    console.log("   ✅ 找到SmAntiFraud实例");
                    
                    // 获取所有方法
                    var methods = instance.class.getDeclaredMethods();
                    console.log("   共有 " + methods.length + " 个方法");
                    
                    // 查找关键方法
                    for (var i = 0; i < methods.length; i++) {
                        var method = methods[i];
                        var methodName = method.getName();
                        
                        if (methodName.indexOf("get") !== -1 || 
                            methodName.indexOf("query") !== -1 ||
                            methodName.indexOf("box") !== -1) {
                            console.log("   - " + methodName);
                        }
                    }
                },
                onComplete: function() {}
            });
            
        } catch (e) {
            console.log("   ⚠️  未找到SmAntiFraud类: " + e);
            console.log("   💡 可能使用了代码混淆，尝试搜索类...");
            
            // 搜索可能的类
            Java.enumerateLoadedClasses({
                onMatch: function(className) {
                    if (className.indexOf("shumei") !== -1 || 
                        className.indexOf("antifraud") !== -1 ||
                        className.indexOf("smsdk") !== -1) {
                        console.log("   找到可疑类: " + className);
                    }
                },
                onComplete: function() {
                    console.log("   搜索完成");
                }
            });
        }
    });
}

// 定时显示捕获摘要
setInterval(function() {
    if (global.capturedAESKey) {
        console.log("\n" + "📊".repeat(50));
        console.log("📊 捕获摘要");
        console.log("═".repeat(100));
        console.log("🔑 AES密钥: " + global.capturedAESKey);
        if (global.capturedIV) {
            console.log("🔑 IV: " + global.capturedIV);
        }
        console.log("⏰ 捕获时间: " + global.capturedAESKeyTime);
        console.log("═".repeat(100));
        console.log("\n💡 使用这个密钥运行 DecryptWithCapturedKey 解密数据！\n");
    }
}, 30000); // 每30秒显示一次

console.log("\n✨ 脚本加载完成，等待初始化...");


